package computacaografica;

import java.awt.image.BufferedImage;

public class Reta extends Geometrico {

	private PontoCart pontoA;

	private PontoCart pontoB;

	public Reta(PontoCart pA, PontoCart pB) {
		this.pontoA = pA;
		this.pontoB = pB;

		int x1 = this.pontoA.getX(), y1 = this.pontoA.getY();
		int x2 = this.pontoB.getX(), y2 = this.pontoB.getY();
		int dx = x2 - x1;
		int dy = y2 - y1;

		if ((dx <= 0) && (dy <= 0)) {
			this.pontoA = pB;
			this.pontoB = pA;
		}
	}

	public void drawDDA(int value, BufferedImage image) {
		int x1 = pontoA.getX(), y1 = pontoA.getY();
		int x2 = pontoB.getX(), y2 = pontoB.getY();

		float x, y, xInc, yInc;
		// distancias
		int dx = x2 - x1;
		int dy = y2 - y1;

		float lenght = Math.abs(dx);
		if (Math.abs(dy) > lenght)
			lenght = Math.abs(dy);

		xInc = dx / lenght;
		yInc = dy / lenght;
		x = x1;
		y = y1;
		if (dx >= dy) {
			while (x < x2) {
				this.paintPoint(Math.round(x), Math.round(y), value, image);
				x += xInc;
				y += yInc;
			}
		} else {
			while (y < y2) {
				this.paintPoint(Math.round(x), Math.round(y), value, image);
				x += xInc;
				y += yInc;
			}
		}
	}

	public void drawPontoMedio(int value, BufferedImage image) {
		// Uses Bresenham's line algorithm
		int x0 = pontoA.getX(), y0 = pontoA.getY();
		int x1 = pontoB.getX(), y1 = pontoB.getY();
		int dy = y1 - y0;
		int dx = x1 - x0;
		int stepx, stepy;
		boolean skip = false;

		if (dy < 0) {
			dy = -dy;
			stepy = -1;
		} else {
			stepy = 1;
		}
		if (dx < 0) {
			dx = -dx;
			stepx = -1;
		} else {
			stepx = 1;
		}
		dy <<= 1; // dy is now 2*dy
		dx <<= 1; // dx is now 2*dx

		this.paintPoint(x0, y0, value, image);
		if (dx > dy) {
			int fraction = dy - (dx >> 1); // same as 2*dy - dx
			while (x0 != x1) {
				if (fraction >= 0) {
					y0 += stepy;
					fraction -= dx; // same as fraction -= 2*dx
				}
				x0 += stepx;
				fraction += dy; // same as fraction -= 2*dy
				if (!skip)
					this.paintPoint(x0, y0, value, image);
				skip = !skip;
			}
		} else {
			int fraction = dx - (dy >> 1);
			while (y0 != y1) {
				if (fraction >= 0) {
					x0 += stepx;
					fraction -= dy;
				}
				y0 += stepy;
				fraction += dx;
				if (!skip)
					this.paintPoint(x0, y0, value, image);
				skip = !skip;
			}
		}

	}

	public Reta transforma(Matriz m) {
		Matriz pontos = this.geraMatrizDePontos();
		Matriz result = m.multiplica(pontos);
		double[] colA = result.getColuna(0);
		double[] colB = result.getColuna(1);

		PontoCart pA = new PontoCart((int)Math.round(colA[0]), (int)Math.round(colA[1]));
		PontoCart pB = new PontoCart((int)Math.round(colB[0]), (int)Math.round(colB[1]));

		return new Reta(pA, pB);
	}

	private Matriz geraMatrizDePontos(){
		double[] linha0 = {this.pontoA.getX(), this.pontoB.getX()};
		double[] linha1 = {this.pontoA.getY(), this.pontoB.getY()};
		double[] linha2 = {1.0,1.0};
		Matriz pontos = new Matriz(3,2);
		pontos.setLinha(0, linha0);
		pontos.setLinha(1, linha1);
		pontos.setLinha(2, linha2);

		return pontos;
	}

	public int getX0(){
		return pontoA.getX();
	}

	public int getY0(){
		return pontoA.getY();
	}

	public int getX1(){
		return pontoB.getX();
	}

	public int getY1(){
		return pontoB.getY();
	}
}
